package service.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import service.WalService;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * WAL（Write-Ahead Log）服务实现类
 * 支持操作日志写入、回放、清理等
 */
@Slf4j
public class WalServiceImpl implements WalService {
    private static final String WAL_FILE = "data/wal.log";
    private static final String CHARSET = "UTF-8";
    private final Object lock = new Object();

    @Override
    public boolean logOperation(String operation, String key, Object value) {
        Map<String, Object> logEntry = new HashMap<>();
        logEntry.put("type", operation);
        logEntry.put("key", key);
        logEntry.put("value", value);
        logEntry.put("ts", System.currentTimeMillis());
        return appendLog(logEntry);
    }

    @Override
    public boolean logBatchOperation(String operation, Map<String, Object> keyValueMap) {
        boolean ok = true;
        for (Map.Entry<String, Object> entry : keyValueMap.entrySet()) {
            ok &= logOperation(operation, entry.getKey(), entry.getValue());
        }
        return ok;
    }

    @Override
    public boolean logDeleteOperation(String key) {
        return logOperation("DELETE", key, null);
    }

    @Override
    public boolean logCollectionOperation(String operation, String collectionName, String key, Object value) {
        Map<String, Object> logEntry = new HashMap<>();
        logEntry.put("type", operation);
        logEntry.put("collection", collectionName);
        logEntry.put("key", key);
        logEntry.put("value", value);
        logEntry.put("ts", System.currentTimeMillis());
        return appendLog(logEntry);
    }

    @Override
    public boolean flush() {
        // 文件IO自动flush，暂不需要实现
        return true;
    }

    @Override
    public boolean replay() {
        // 回放日志，供外部调用
        // 具体回放逻辑由调用方实现
        return true;
    }

    @Override
    public boolean cleanup() {
        synchronized (lock) {
            try {
                File file = new File(WAL_FILE);
                if (file.exists()) {
                    boolean deleted = file.delete();
                    if (deleted) {
                        log.info("WAL日志已清理");
                    }
                    return deleted;
                }
            } catch (Exception e) {
                log.error("清理WAL日志失败: {}", e.getMessage());
            }
            return false;
        }
    }

    @Override
    public Map<String, Object> getStatistics() {
        Map<String, Object> stat = new HashMap<>();
        File file = new File(WAL_FILE);
        stat.put("exists", file.exists());
        stat.put("size", file.length());
        return stat;
    }

    @Override
    public boolean checkpoint() {
        // checkpoint后可清理日志
        return cleanup();
    }

    @Override
    public List<String> getUncommittedLogs() {
        List<String> logs = new ArrayList<>();
        synchronized (lock) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(WAL_FILE), CHARSET))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    logs.add(line);
                }
            } catch (IOException e) {
                // 文件不存在时返回空
            }
        }
        return logs;
    }

    @Override
    public boolean markCommitted(String logId) {
        // 简化实现：不做单条标记，回放后整体清理
        return true;
    }

    private boolean appendLog(Map<String, Object> logEntry) {
        synchronized (lock) {
            try (FileWriter fw = new FileWriter(WAL_FILE, true)) {
                fw.write(JSONObject.toJSONString(logEntry));
                fw.write("\n");
                fw.flush();
                return true;
            } catch (IOException e) {
                log.error("写入WAL日志失败: {}", e.getMessage());
                return false;
            }
        }
    }
} 